package restless.core.gameObjs {

	import com.greensock.motionPaths.RectanglePath2D;
	import com.greensock.plugins.ColorMatrixFilterPlugin;
	import com.greensock.TimelineMax;
	import com.greensock.TweenMax;
	import flash.filters.BitmapFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.geom.Vector3D;
	import flash.globalization.StringTools;
	import flash.media.Camera;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.text.Font;
	import flash.text.TextField;
	import flash.text.TextFormat;
	
	import restless.core.RLECamera;
	import restless.core.RLETickTimer;
	import restless.core.RLEXMLData;
	
	import restless.core.interfaces.I2d;
	import restless.core.interfaces.ITimer;
	import restless.core.managers.RLEColisionManager;
	import restless.core.managers.RLEGraphicsManager;
	import restless.core.managers.RLELevelManager;
	import restless.core.managers.RLEPowerupManager;
	import restless.core.managers.RLEScreenManager;
	import restless.core.managers.RLEStatManager;
	import restless.core.managers.RLETweenManager;
	import restless.core.managers.RLESoundManager;
	import restless.core.managers.RLETextManager;
	import restless.core.managers.RLEXMLManager;
	
	import restless.core.interfaces.ICreateTimers;
	import restless.core.interfaces.IKeyControled;
	import restless.core.interfaces.IMouseControled;
	import restless.core.interfaces.IScore;
	import restless.core.managers.RLEKeyboardManager;
	import restless.core.managers.RLEMouseManager;
	import restless.core.managers.RLETimerManager;
	import restless.utilities.display.RLEMatrixTransformer;
	
	/**
	 * 
	 * @author Jordan Laine
	 * 
	 */
	
	public class RLEManagedObj extends RLEUpdateRenderObj implements I2d, IMouseControled, IKeyControled, ICreateTimers {
		
		protected var statM:RLEStatManager;
		protected var gfxM:RLEGraphicsManager;
		protected var screenM:RLEScreenManager;
		protected var levelM:RLELevelManager;
		protected var timerM:RLETimerManager;
		protected var mouseM:RLEMouseManager;
		protected var keyM:RLEKeyboardManager;
		protected var tweenM:RLETweenManager;
		protected var colM:RLEColisionManager;
		protected var powerM:RLEPowerupManager;
		protected var textM:RLETextManager;
		protected var soundM:RLESoundManager;
		protected var xmlM:RLEXMLManager;
		
		private var bTimerManager:Boolean = false;
		private var bKeyboardManager:Boolean = false;
		private var bTextManager:Boolean = false;
		private var bXML:Boolean = false;
		
		protected var dx:Number;
		protected var dy:Number;
		
		private var _rect:Rectangle;
		private var _clickL:Boolean;
		private var _clickR:Boolean;
		private var _mouseOver:Boolean;
		private var _over:Boolean;
		private var _wheel:Boolean;
		private var _timers:Boolean;
		private var _keyboard:Boolean;
		private var _text:Boolean;
		private var _xml:Boolean;
		
		private var _visible:Boolean;
		private var _center:Boolean;
		private var _pause:Boolean = false;
		private var _scaleX:Number = 1;
		private var _scaleY:Number = 1;
		private var _rotation:Number = 0;
		private var _rotationPoint:Point;
		private var _flip:Boolean = false;
		private var _xOff:Number;
		private var _yOff:Number;
		private var _renderWidth:Number;
		private var _renderHeight:Number;
		private var _width:Number;
		private var _height:Number;
		private var _layer:int;
		private var _z:Number;
		
		private var _screenPri:int;
		private var _mousePriority:int = 1;
		private var _bitmap:Bitmap;
		private var _bitmapData:BitmapData;
		private var _clickGlobal:Boolean = false;
		private var _BKGing:Boolean = false;
		private var _overlaying:Boolean = false;
		private var _parallaxing:Boolean = false;
		private var _transformMatrix:Matrix = new Matrix;
		private var _colorTransform:ColorTransform;
		private var _alpha:Number = 100;
		private var _color:uint = 0x00000000;
		
		protected var xmlData:RLEXMLData;
		
		protected var vTextIDs:Vector.<String>;
		protected var vTextObjs:Vector.<RLETextObj>;
		protected var tempTextObj:RLETextObj;
		
		protected var bColorTransform:Boolean = false;
		protected var bFilter:Boolean = false;
		protected var _filter:Array = [];
		
		protected var timeLine:TimelineMax;
		protected var tween:TweenMax;
		
		protected var vTimers:Vector.<ITimer>;
		protected var vInput:Vector.<int>;
		protected var vInputActions:Vector.<String>;
		
		protected var i:int;
		protected var tempBitmap:Bitmap;
		protected var tempBitmapData:BitmapData;
		protected var tempString:String;
		protected var tempBool:Boolean;
		protected var tempRect:Rectangle;
		protected var tempV3DPoint:Vector3D;
		protected var tempPoint:Point;
		protected var tempBlitMC:RLEBlitMC;
		protected var vBlitMC:Vector.<RLEBlitMC>;
		protected var vBlitMCID:Vector.<String>;
		protected var tempTimer:ITimer;
		
		override public function setRE():void {
			super.setRE();
			
			statM = RE.statM;
			gfxM = RE.gfxM;
			screenM = RE.screenM;
			levelM = RE.levelM;
			timerM = RE.timerM;
			mouseM = RE.mouseM;
			keyM = RE.keyM;
			tweenM = RE.tweenM;
			colM = RE.colM;
			powerM = RE.powerM;
			textM = RE.textM;
			soundM = RE.soundM;
			xmlM = RE.xmlM;
			
			_rect = new Rectangle;
			tempRect = new Rectangle;
			tempV3DPoint = new Vector3D;
			tempPoint = new Point;
		}
		
		public function addText(id:String, text:String, format:String, x:Number = 0, y:Number = 0):RLETextObj {
			if (vTextIDs == null) {
				vTextIDs = new Vector.<String>;
				vTextObjs = new Vector.<RLETextObj>;
			}
			tempTextObj = new RLETextObj();
			tempTextObj.setOutFormat( textM.getTextFormat(format) );
			tempTextObj.sID = id;
			tempTextObj.text = text;
			tempTextObj.x = x;
			tempTextObj.y = y;
			
			vTextObjs.push( tempTextObj );
			vTextIDs.push( id );
			
			return tempTextObj;
		}
		
		public function changeText(id:String, text:String):void {
			tempTextObj = getText(id);
			tempTextObj.text = id;
		}
		
		public function removeText(id:String):void {
			i = vTextIDs.indexOf(id);
			tempTextObj = vTextObjs[i];
			tempTextObj.dispose();
			vTextIDs.splice(i, 1);
			vTextObjs.splice(i, 1);
		}
		
		public function removeAllText():void {
			if (vTextObjs == null) { return; }
			i = vTextObjs.length -1;
			for (i; i > -1; i--) {
				tempTextObj = vTextObjs[i];
				tempTextObj.dispose();
			}
			vTextObjs.length = 0;
			vTextIDs.length = 0;
		}
		
		public function getText(id:String):RLETextObj {
			if (vTextObjs.length == 1) { return vTextObjs[0]; }
			var num:int = vTextIDs.indexOf(id);
			if (num > -1) {
				return vTextObjs[num];
			}
			return null;
		}
		
		public function setInputActions(actions:Vector.<String>):void {
			vInputActions = actions;
		}
		
		public function input(action:String):void {
			
		}
		
		public function mMove(mouse:Point):void {
			tempBool = hitTestPoint(mouse);
			if ( _over == tempBool ) { return; } 
			
			_over = tempBool;
			if (!_over) {
				mOut();
			} else {
				mOver();
			}
		}
		
		public function addBlitMC(id:String, bitmapData:Vector.<BitmapData>, layer:int, update:Boolean, center:Boolean ):RLEBlitMC {
			if (vBlitMC == null) {
				vBlitMC = new Vector.<RLEBlitMC>;
				vBlitMCID = new Vector.<String>;
			}
			tempBlitMC = new RLEBlitMC();
			tempBlitMC.setRE();
			tempBlitMC.switchGFX(bitmapData, center);
			tempBlitMC.updating = update;
			tempBlitMC.layer = layer;
			tempString = id;
			tempBlitMC.sID = tempString;
			
			vBlitMCID.push(tempString);
			vBlitMC.push(tempBlitMC);
			return tempBlitMC;
		}
		
		public function removeBlitMC(id:String):void {
			i = vBlitMCID.indexOf(id);
			if (i > -1) {
				tempBlitMC = vBlitMC[i];
				tempBlitMC.dispose();
				vBlitMC.splice(i, 1);
				vBlitMCID.splice(i, 1);
			}
		}
		
		public function removeAllBlitMC():void {
			i = vBlitMC.length - 1;
			for (i; i > -1; i--) {
				vBlitMC[i].dispose();
			}
			vBlitMC.length = 0;
			vBlitMCID.length = 0;
		}
		
		public function mOver():void {
			
		}
		
		public function mOut():void {
			
		}
		
		public function mClickL():void {
			
		}
		
		public function mClickR():void {
			
		}
		
		public function mWheelUp():void {
			
		}
		
		public function mWheelDown():void {
			
		}
		
		public function addTickTimer(id:String, timeToWait:int, loop:Boolean=false, manualDispose:Boolean=false):void {			
			vTimers.push( timerM.addTickTimer(id, timeToWait, this, loop, manualDispose) );
		}
		
		public function executeTimer(id:String):void {
			
		}
		
		public function getTimer(id:String):ITimer {
			i = vTimers.length -1;
			var tempTimer:ITimer;
			for (i; i > -1; i--) {
				tempTimer = vTimers[i];
				if (id == tempTimer.sID) {
					return tempTimer;
				}
			}
			return null;
		}
		
		public function removeTimerByName(id:String):void {
			i = vTimers.length -1;
			var tempTimer:ITimer;
			for (i; i > -1; i--) {
				tempTimer = vTimers[i];
				if (id == tempTimer.sID) {
					vTimers.splice(i, 1);
					return;
				}
			}
		}
		
		public function removeTimer(timer:ITimer):void {
			
			var num:int = vTimers.indexOf(timer);
			if (num > -1) {
				vTimers.splice(num, 1);
			}
		}
		
		public function set leftClick(bool:Boolean):void {
			if (_clickL == bool) { return; }
			_clickL = bool;
			
			mouseM.leftClickList(this, _clickL);
		}
		
		public function set rightClick(bool:Boolean):void {
			if (_clickR == bool) { return; }
			_clickR = bool;
			
			mouseM.rightClickList(this, _clickR);
		}
		
		public function set mouseOver(bool:Boolean):void {
			if (_mouseOver == bool) { return; }
			_mouseOver = bool;
			
			mouseM.mouseOverList(this, _mouseOver);
		}
		
		public function set mouseWheel(bool:Boolean):void {
			if (_wheel == bool) { return; }
			_wheel = bool;
			
			mouseM.mouseWheelList(this, _wheel);
		}
		
		public function set keyboard(bool:Boolean):void {
			if (_keyboard == bool ) { return; }
			_keyboard = bool;
			
			if (_keyboard) {
				keyM.addToKeyboardListen(this);
			} else {
				keyM.removeFromKeyboardListen(this);
			}
		}
		
		public function set timers(bool:Boolean):void {
			if (_timers == bool) { return; }
			_timers = bool;
			
			if (_timers) {
				if (vTimers == null) {
					vTimers = new Vector.<ITimer>;
				}
			} else {
				if (vTimers.length > 0) {
					timerM.removeTimersByArray(vTimers);
					vTimers.length = 0;
				}
			}
		}
		
		public function set xml(bool:Boolean):void {
			if (_xml == bool) { return; }
			_xml = bool;
			
			if (_xml) {
				xmlData = xmlM.getXMLData(sID);
			} else {
				xmlData = null;
			}
			
		}
		
		public function hitTestPoint(point:Point):Boolean {
			tempRect = new Rectangle(point.x, point.y, 1, 1);
			
			if (_rect.right < tempRect.left || _rect.left > tempRect.right ||
			_rect.top > tempRect.bottom || _rect.bottom < tempRect.top ) {
				tempBool = false;
			} else {
				tempBool = true;
			}
			
			return tempBool;
		}
		
		public function insideOfRect(r:Rectangle):Boolean {
			tempRect = r;
			
			if (_rect.right < tempRect.left || _rect.left > tempRect.right ||
			_rect.top > tempRect.bottom || _rect.bottom < tempRect.top ) {
				tempBool = false;
			} else {
				tempBool = true;
			}
			
			return tempBool;
		}
		
		public function forceRender():void {
			tempBool = false;
			if (!_visible) {
				_visible = true;
				tempBool = true;
			}
			
			render();
			
			if (tempBool) {
				_visible = false;
			}
		}
		
		public function isNull():Boolean {
			if (_bitmapData == null && _bitmap == null && rect == null) {
				return true;
			} else {
				return false;
			}
		}
		
		public function set visible(bool:Boolean):void {
			_visible = bool;
		}
		
		public function get visible():Boolean {
			return _visible;
		}
		
		override public function get rendering():Boolean {
			return super.rendering;
		}
		
		override public function set rendering(value:Boolean):void {
			super.rendering = value;
			if (!rendering) {
				_visible = false;
			}
		}
		public function setRenderBoundary(w:Number, h:Number):void {		
			_renderWidth = w;
			_renderHeight = h;
		}
		
		public function get renderRect():Rectangle {
			tempRect.x = 0;
			tempRect.y = 0;
			tempRect.width = _renderWidth * scaleX;
			tempRect.height = _renderHeight * _scaleY;
			
			if (rotation != 0) {
				tempRect = boundingRect();
				trace("bounding rect " + boundingRect());
				return boundingRect();
			}
			return tempRect;
		}
		
		public function get bitmapData():BitmapData {
			return _bitmapData;
		}
		
		public function set bitmapData(bitmapData:BitmapData):void {
			_bitmapData = bitmapData;
		}
		
		public function get bitmap():Bitmap {
			return _bitmap;
		}
		
		public function set bitmap(bitmap:Bitmap):void {
			_bitmap = bitmap;
		}
		
		public function get screenPriority():int {
			return _screenPri;
		}
		
		public function set mousePriority(priority:int):void {
			_mousePriority = priority;
		}
		
		public function get mousePriority():int {
			return _mousePriority;
		}
		
		public function set clickGlobal(bool:Boolean):void {
			_clickGlobal = bool;
		}
		
		public function get clickGlobal():Boolean {
			return _clickGlobal;
		}
		
		public function set center(bool:Boolean):void {
			if (_center == bool) { return; }
			_center = bool;
			
			if (_center) {
				updateCenterXY();
				_rect.x += _xOff;
				_rect.y += _yOff;
			} else {
				_rect.x -= _xOff;
				_rect.y -= _yOff;
				updateCenterXY();
			}
		}
		
		public function get center():Boolean {
			return _center;
		}
		
		public function updateCenterXY():void {
			_xOff = _rect.width * -.5;
			_yOff = _rect.height * -.5;
		}
		
		public function get centerX():Number {
			return _xOff;
		}
		
		public function get centerY():Number {
			return _yOff;
		}
		
		public function get centerPoint():Point {
			tempPoint.x = _xOff;
			tempPoint.y = _yOff;
			return tempPoint;
		}
		
		public function get x():Number {
			return _rect.x;
		}
		
		public function set x(num:Number):void {
			_rect.x = num;
		}
		
		public function get y():Number {
			return _rect.y;	
		}
		
		public function set y(num:Number):void {
			_rect.y = num;
		}
		
		public function get z():Number {
			return _z;
		}
		
		public function set z(num:Number):void {
			_z = num;
		}
		
		public function set rect(rect:Rectangle):void { 
			tempRect = rect;
			_width = tempRect.width;
			_height = tempRect.height;
			_rect.x = tempRect.x;
			_rect.y = tempRect.y;
			_rect.width = _width * _scaleX;
			_rect.height = _height * _scaleY;
		}
		
		public function get rect():Rectangle {
			return _rect;
		}
		
		public function setRect(x:Number, y:Number, w:Number, h:Number):void {
			_width = w;
			_height = h;
			_rect.x = x;
			_rect.y = y;
			_rect.width = _width * _scaleX;
			_rect.height = _height * _scaleY;
		}
		
		public function get width():Number {
			return _rect.width;
		}
		
		public function set width(num:Number):void {
			_width = num;
			_rect.width = _width * scaleX;
		}
		
		public function get height():Number {
			return _rect.height;
		}
		
		public function set height(num:Number):void {
			_height = num;
			_rect.height = _height * scaleY;
		}
		
		public function setScale(x:Number = 1, y:Number = 1):void {
			if (x == _scaleX && y == _scaleY) { return; }
			_scaleX = x;
			_scaleY = y;
			_rect.width = _width * _scaleX;
			_rect.height = _height * _scaleY;
			setTransformMatrix();
		}
		
		public function get scaleX():Number {
			return _scaleX;
		}
		
		public function get scaleY():Number {
			return _scaleY;
		}
		
		public function set layer(layer:int):void {
			_layer = layer;
			if (_parallaxing) {
				screenM.changeParallaxObjLayer(this, _layer);
			}
		}
		
		public function get layer():int {
			return _layer;
		} 
		
		public function set pause(bool:Boolean):void {
			if (bool == _pause) { return; } 
			_pause = bool;
		}
		
		public function get pause():Boolean {
			return _pause;
		}
		
		public function set rotation(rot:Number):void {
			_rotation = rot;
			setTransformMatrix();
		}
		
		public function get rotation():Number {
			return _rotation;
		}
		
		public function get rotationPoint():Point {
			return _rotationPoint;
		}
		
		public function set rotationPoint(p:Point):void {
			_rotationPoint = p;
		}
		
		private function setTransformMatrix():void {
			if (!_transformMatrix) {
				_transformMatrix = new Matrix;
			}
			
			_transformMatrix.identity();
			_transformMatrix.scale(scaleX, scaleY);
			
			var bRot:Boolean = (_rotation == 0) ? false : true;
			
			if (bRot) {
				if (_rotationPoint != null) {
					_transformMatrix.rotate(_rotation * 0.017453293);
					_transformMatrix.translate(_rotationPoint.x, _rotationPoint.y);
				} else if (_center) {
					_transformMatrix.translate(-centerX, -centerY);
					_transformMatrix.rotate(_rotation * 0.017453293);
					_transformMatrix.translate(centerX, centerY);
				} else {
					_transformMatrix.rotate(_rotation * 0.017453293);
				}
			}
		}
		
		public function boundingRect():Rectangle {
			var x1:Number = (x - centerX) * Math.cos(_rotation) - (y - centerY) * Math.sin(_rotation);
			var y1:Number = (x - centerX) * Math.sin(_rotation) + (y - centerY) * Math.cos(_rotation);
			
			var x1a:Number = (x - centerX) * Math.cos(_rotation) - (height - centerX) * Math.sin(_rotation);
			var y1a:Number = (x - centerX) * Math.sin(_rotation) + (height - centerX) * Math.cos(_rotation);
			
			var x2:Number = (width - centerX) * Math.cos(_rotation) - (height - centerX) * Math.sin(_rotation);
			var y2:Number = (width - centerX) * Math.sin(_rotation) + (height - centerX) * Math.cos(_rotation);
		 
			var x2a:Number = (width - centerX) * Math.cos(_rotation) - (y - centerY) * Math.sin(_rotation);
			var y2a:Number = (width - centerX) * Math.sin(_rotation) + (y - centerY) * Math.cos(_rotation);         
			
			var rx1:Number = centerX + Math.min(x1, x2, x1a, x2a);
			var ry1:Number = centerY + Math.min(y1, y2, y1a, y2a);
			
			var rx2:Number = centerX + Math.max(x1, x2, x1a, x2a);
			var ry2:Number = centerY + Math.max(y1, y2, y1a, y2a);
			
			return new Rectangle(rx1, ry1, rx2 - rx1, ry2 - ry1);           
		}
		
		public function get parallaxing():Boolean {
			return _parallaxing;
		}
		
		public function set parallaxing(bool:Boolean):void {
			if (_parallaxing == bool) { return; }
			_parallaxing = bool;
			if (_parallaxing) {
				screenM.addParallaxObj(this);
			} else {
				screenM.removeParallaxObj(this);
			}
		}
		
		public function get backgroundObj():Boolean {
			return _BKGing;
		}
		
		public function set backgroundObj(bool:Boolean):void {
			if (_BKGing == bool) { return; }
			_BKGing = bool;
			if (_BKGing) {
				screenM.addBKGingToScreen(this);
			} else {
				screenM.removeBKGingFromScreen(this);
			}
		}
		
		public function get overlaying():Boolean {
			return _overlaying;
		}
		
		public function set overlaying(bool:Boolean):void {
			if (_overlaying == bool) { return; }
			_overlaying = bool;
			if (_overlaying) {
				screenM.addOverlayingToScreen(this);
			} else {
				screenM.removeOverlayingFromScreen(this);
			}
		}
		
		public function get transformMatrix():Matrix {
			return _transformMatrix;
		}
		
		public function set transformMatrix(value:Matrix):void {
			_transformMatrix = value;
		}
		
		public function get filters():Array {
			return _filter;
		}
		
		public function set filters(a:Array):void {
			_filter = a;
		}
		
		public function get colorTransform():ColorTransform {
			return _colorTransform;
		}
		
		public function set colorTransform(ct:ColorTransform):void {
			_colorTransform = ct;
			if (_colorTransform != null) { 
				bColorTransform = true;
				forceRender();
			} else { 
				bColorTransform = false; 
			}
		}
		
		public function get alpha():Number {
			return _alpha;
		}
		
		public function set alpha(value:Number):void {
			_alpha = value;
			if (_alpha > 100) { _alpha = 100;}
			if (_alpha < 0) { _alpha = 0;}
			
			if (_colorTransform == null) {
				colorTransform = new ColorTransform(1, 1, 1, _alpha);
			} else {
				_colorTransform.alphaMultiplier = _alpha;
			}
			trace("alpha = " + _alpha);
		}
		
		public function addfilter(filter:BitmapFilter):void {
			if (filter == null) { return; }
			
			_filter.push(filter);
			bFilter = true;
		}
		
		public function toggleFilters(bool:Boolean):void {
			if (bool) {
				if (_filter.length < 1) {
					return;
				}
			}
			
			bFilter = bool;
		}
		
		override public function dispose():void {
			mouseOver = false;
			keyboard = false;
			rightClick = false;
			leftClick = false;
			
			removeAllText();
			parallaxing = false;
			backgroundObj = false;
			overlaying = false;
			
			tempTimer = null;
			tempTextObj = null;
			tempRect = null;
			tempPoint = null;
			tempV3DPoint = null;
			_bitmapData = null;
			_bitmap = null;
			timeLine = null;
			tween = null;
			_rect = null;
			_colorTransform = null;
			
			vInput = null;
			vTimers = null;
			vInputActions = null;
			vTextObjs = null;
			vTextIDs = null;
			vBlitMC = null;
			vBlitMCID = null;
			
			timerM = null;
			mouseM = null;
			keyM = null;
			soundM = null;
			tweenM = null;
			gfxM = null;
			colM = null;
			levelM = null;
			screenM = null;
			powerM = null;
			statM = null;
			textM = null;
			xmlM = null;
			
			super.dispose();
		}
	}
}

